import { useCallback } from "react";
import { useBasicStore } from "../stores/useBasicStore";
import { message } from "antd";
import type { AxiosResponse } from "axios";
import type { IBaseResponse } from "../interface/api";

/**
 * 请求hooks
 * 支持全局状态管理loading
 * @param props.apiFunc 请求函数
 * @param props.options 各种配置项, showErrorMsg: 是否展示错误信息, showSuccessInfo: 是否展示成功信息
 * @param props.setlocalLoading 用于设置局部loading, 当传入这个值的时候表示不使用全局loading
 * @returns request 包装后的请求函数
 */
const useRequest = <Args extends unknown[], Data>(
  apiFunc: ((...args: Args) => Promise<AxiosResponse<IBaseResponse<Data>>>),
  options: {
    showErrorMsg?: boolean | ((err: string) => void)
    showSuccessInfo?: boolean | ((info: string) => void)
  } = {},
  setLocalLoading?: (bol: boolean) => void
): ((...args: Args) => Promise<Data | undefined>) => {
  // 解构获取配置项
  const { showErrorMsg = true, showSuccessInfo = false } = options;
  // 从全局状态里面获取设置加载中函数
  const { setLoading } = useBasicStore()
  // 包装过的请求函数
  const request = useCallback(async (...args: Args) => {
    // 如果传入了第三个参数就使用局部设置加载loading, 否则使用全局loading
    const setRequestLoading = (typeof setLocalLoading === 'function') ? setLocalLoading : setLoading;
    try {
      // 请求开始设置为加载中
      setRequestLoading(true);
      // 等待请求结束
      const result = await apiFunc(...args);
      // 解构结果
      const { data, msg, code, errMsg } = result.data
      // 如果返回的结果的code是1的话
      if (code) {
        // 如果要显示成功, 显示成功
        if (showSuccessInfo) {
          if (typeof showSuccessInfo === 'function') showSuccessInfo(msg || '请求成功')
          else message.success(msg || '请求成功')
        }
      } else {
        // 否则, 如果要显示失败, 显示失败
        if (showErrorMsg) {
          if (typeof showErrorMsg === 'function') showErrorMsg(errMsg || msg || '请求失败, 请稍后重试~')
          else message.info(errMsg || msg || '请求失败, 请稍后重试~')
        }
      }
      // 返回data结果
      return data;
    } catch (error) {
      // 捕获错误
      console.log(error);
      if (showErrorMsg) {
        if (typeof showErrorMsg === 'function') showErrorMsg('内部错误, 请稍后重试~')
        else message.info('内部错误, 请稍后重试~')
      }
      throw error
    } finally {
      // 请求结束, 设为未加载
      setRequestLoading(false);
    }
  }, [apiFunc, showErrorMsg, showSuccessInfo, setLocalLoading, setLoading])
  return request
}

export default useRequest
